package demo03_producerProblem;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author kunkun
 * @className Solution_juc_pro
 * @Description JUC并发编程解决生产者消费者问题--进阶，指定执行顺序
 * @date 2025/3/5 17:00
 */
public class Solution_juc_pro {

    public static void main(String[] args) {
        Problem problem = new Problem();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    problem.produce();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"A").start();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    problem.consume_B();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    problem.consume_C();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"C").start();




    }



    static class Problem{

        private Lock lock = new ReentrantLock();
        private Condition conditionA = lock.newCondition();
        private Condition conditionB = lock.newCondition();
        private Condition conditionC = lock.newCondition();

        int num=0;
        boolean flag=true;  //true：B先执行，false：C先执行

        public void produce() throws InterruptedException {
            lock.lock();
            try {
                while (num==1){
                    conditionA.await();
                }
                num++;
                System.out.println(Thread.currentThread().getName()+"--->"+num);
                if (flag){
                    flag=!flag;
                    conditionB.signal();
                }else {
                    flag=!flag;
                    conditionC.signal();
                }
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }finally {
                lock.unlock();
            }
        }

        public void consume_B() throws InterruptedException {
            lock.lock();
            try {
                while (num==0){
                    conditionB.await();
                }
                num--;
                System.out.println(Thread.currentThread().getName()+"--->"+num);
                conditionA.signal();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }

        public void consume_C() throws InterruptedException {
            lock.lock();
            try {
                while (num==0){
                    conditionC.await();
                }
                num--;
                System.out.println(Thread.currentThread().getName()+"--->"+num);
                conditionA.signal();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            } finally {
                lock.unlock();
            }
        }


    }


}
